package com.tuo51.evaluate.service.impl;

import com.google.common.collect.ImmutableMap;
import com.tuo51.core.domain.org.Organization;
import com.tuo51.core.domain.staffs.Staff;
import com.tuo51.core.service.StaffService;
import com.tuo51.evaluate.domain.childrens.Children;
import com.tuo51.evaluate.domain.childrens.ChildrenExtendInfo;
import com.tuo51.evaluate.domain.childrens.RelStaffChildren;
import com.tuo51.evaluate.repositories.children.ChildrenExtendInfoRepository;
import com.tuo51.evaluate.repositories.children.ChildrenRepository;
import com.tuo51.evaluate.repositories.children.RelStaffChildrenRepository;
import com.tuo51.evaluate.service.ChildrenService;
import com.tuo51.evaluate.vo.children.ChildrenExtendInfoVO;
import com.tuo51.evaluate.vo.children.ChildrenPO;
import com.tuo51.evaluate.vo.children.ChildrenVO;
import com.tuo51.foudation.exception.BusinessException;
import com.tuo51.foudation.model.ErrorCode;
import com.tuo51.foudation.model.MemVerificationCache;
import com.tuo51.foudation.utils.CopyUtils;
import com.tuo51.foudation.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * *******************************
 * Created by Tim.
 * form com.matt
 * on 2017/7/13
 * *******************************
 */
@Service
@Slf4j
public class ChildrenServiceImpl implements ChildrenService {

    @Autowired
    private ChildrenRepository childrenRepository;

    @Autowired
    private ChildrenExtendInfoRepository childrenExtendInfoRepository;

    @Autowired
    private RelStaffChildrenRepository rscRepository;

    @Autowired
    private MemVerificationCache cache;

    @Autowired
    private StaffService staffService;

    @Value("${spring.profiles.active}")
    private String env;

    @Transactional
    @Override
    public Children add(ChildrenVO childrenVO){
        if (StringUtils.isNotEmpty(childrenVO.getId())){
            throw new BusinessException(ErrorCode.OPERATION_DUPLICATED, "重复的对象？");
        }

        Children children = new Children();

        CopyUtils.copyProperties(childrenVO, children);

        childrenRepository.save(children);

        ChildrenExtendInfo extendInfo = ChildrenExtendInfo.of(children.getId(), children.getName());
        if (childrenVO.getExtendInfo() != null) {
            CopyUtils.copyProperties(childrenVO.getExtendInfo(), extendInfo);
        }
        childrenExtendInfoRepository.saveAndFlush(extendInfo);

        children.setExtendInfo(extendInfo);

        return children;
    }

    @Transactional
    @Override
    public Children add(String staffId,
                            String childAvatarUrl,
                            String childrenName,
                            String nickName,
                            Integer gender,
                            String birthday,
                            String weight, String height, String parentPhone,String guardianName, String guardianRelation){

        Children children = new Children();
        children.setName(childrenName);
        children.setImgUrl(childAvatarUrl);
        children.setNickName(nickName);
        children.setGender(gender);
        children.setBirthday(DateUtil.parseToDate(birthday));
        children.setHeight(height);
        children.setWeight(weight);

        children.setStaffId(staffId);

        childrenRepository.save(children);

        //添加一个宝宝的扩展信息
        ChildrenExtendInfo extendInfo = ChildrenExtendInfo.of(children.getId(), children.getName());
        extendInfo.setGuardianPhone(parentPhone);
        extendInfo.setGuardianRelation(guardianRelation);
        extendInfo.setGuardianName(guardianName);
        childrenExtendInfoRepository.save(extendInfo);

        return children;
    }

    @Transactional
    @Override
    public Children edit(Children children, ChildrenVO childrenVO){

        if (children == null ){
            if (StringUtils.isNotEmpty(childrenVO.getId())) {
                children = childrenRepository.getOne(childrenVO.getId());
            }
            if (children == null){
                throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "参数错误");
            }
        }

        if (StringUtils.isNotEmpty(childrenVO.getName()))
            children.setName(childrenVO.getName());

        if (StringUtils.isNotEmpty(childrenVO.getNickName()))
            children.setNickName(childrenVO.getNickName());

        if (childrenVO.getBirthday() != null)
            children.setBirthday(childrenVO.getBirthday());

        if (childrenVO.getGender() != null)
            children.setGender(childrenVO.getGender());

        if (StringUtils.isNotEmpty(childrenVO.getImgUrl()))
            children.setImgUrl(childrenVO.getImgUrl());

        if (StringUtils.isNotEmpty(childrenVO.getWeight()))
            children.setWeight(childrenVO.getWeight());

        if (StringUtils.isNotEmpty(childrenVO.getHeight()))
            children.setHeight(childrenVO.getHeight());

        if (StringUtils.isNotEmpty(childrenVO.getHeader()))
            children.setHeader(childrenVO.getHeader());

        if (StringUtils.isNotEmpty(childrenVO.getRemark()))
            children.setRemark(childrenVO.getRemark());

        ChildrenExtendInfoVO extInfo = childrenVO.getExtendInfo();
        if (extInfo != null){
            ChildrenExtendInfo extendInfo = children.getExtendInfo();
            if (extendInfo == null) {
                extendInfo = childrenExtendInfoRepository.findByChildrenId(children.getId());
            }
            if (StringUtils.isNotEmpty(extInfo.getGuardianName()))
                extendInfo.setGuardianName(extInfo.getGuardianName());
            if (StringUtils.isNotEmpty(extInfo.getGuardianRelation()))
                extendInfo.setGuardianRelation(extInfo.getGuardianRelation());
            if (StringUtils.isNotEmpty(extInfo.getGuardianPhone()))
                extendInfo.setGuardianPhone(extInfo.getGuardianPhone());

            if (StringUtils.isNotEmpty(extInfo.getHouseholdType()))
                extendInfo.setHouseholdType(extInfo.getHouseholdType());

            if (StringUtils.isNotEmpty(extInfo.getIdentityCard()))
                extendInfo.setIdentityCard(extInfo.getIdentityCard());

            if (StringUtils.isNotEmpty(extInfo.getGoodLanguageDesc()))
                extendInfo.setGoodLanguageDesc(extInfo.getGoodLanguageDesc());

            childrenExtendInfoRepository.save(extendInfo);
        }

        return childrenRepository.save(children);
    }

    @Override
    public Children createOrEdit(Staff staff, ChildrenPO po, Organization org ){
        Children children = null;

        if (!StringUtils.isEmpty(po.getId())) {
            children = getById(staff.getId(), po.getId());
            if (children == null) {
                throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "宝宝不存在");
            }
        } else {
            if (StringUtils.isAnyEmpty(po.getName(), po.getBirthday()) || po.getGender() == null){
                throw new BusinessException(ErrorCode.PARAM_CAN_NOT_BLANK, "参数不能为空");
            }

            children = new Children();
            children.setStaffId(staff.getId());
            children.setOrgId(org.getId());
            children.setName(po.getName());
            childrenRepository.save(children);

            ChildrenExtendInfo extendInfo = ChildrenExtendInfo.of(children.getId(), children.getName());
            childrenExtendInfoRepository.saveAndFlush(extendInfo);
        }
        {
            ChildrenVO vo = new ChildrenVO();
            CopyUtils.copyProperties(po, vo);
            vo.setBirthday(DateUtil.parseToDate(po.getBirthday()));

            if (!StringUtils.isAllBlank(po.getGuardianName(), po.getGuardianPhone(), po.getGuardianRelation(), po.getAddress())){
                ChildrenExtendInfoVO extendInfoVO = new ChildrenExtendInfoVO();
                CopyUtils.copyProperties(po, extendInfoVO);
                vo.setExtendInfo(extendInfoVO);
            }

            children = edit(children, vo);
        }

        return children;
    }

    @Transactional
    @Override
    public Children edit(Children children, String name, String nickName, String avatar,
                         String guardianPhone, String guardianName, String guardianRelation, String birthday,
                         Integer gender, String weight, String height, String header, String address, String remark) {

        ChildrenVO vo = new ChildrenVO();

        if (StringUtils.isNotEmpty(name))
            vo.setName(name);

        if (StringUtils.isNotEmpty(nickName))
            vo.setNickName(nickName);

        if (StringUtils.isNotEmpty(birthday))
            vo.setBirthday(DateUtil.parseToDate(birthday));

        if (gender != null)
            vo.setGender(gender);

        if (StringUtils.isNotEmpty(avatar))
            vo.setImgUrl(avatar);

        if (StringUtils.isNotEmpty(weight))
            vo.setWeight(weight);

        if (StringUtils.isNotEmpty(height))
            vo.setHeight(height);

        if (StringUtils.isNotEmpty(header))
            vo.setHeader(header);

        if (StringUtils.isNotEmpty(remark))
            vo.setRemark(remark);

        ChildrenExtendInfoVO extendInfo = new ChildrenExtendInfoVO();
        vo.setExtendInfo(extendInfo);
        if (!StringUtils.isAllEmpty(guardianName, guardianPhone, guardianRelation)){
            if (StringUtils.isNotEmpty(guardianName))
                extendInfo.setGuardianName(guardianName);
            if (StringUtils.isNotEmpty(guardianRelation))
                extendInfo.setGuardianRelation(guardianRelation);
            if (StringUtils.isNotEmpty(guardianPhone))
                extendInfo.setGuardianPhone(guardianPhone);
        }


        return edit(children, vo);
    }

    @Override
    public Children getById(String id) {
        Children ret = childrenRepository.getOne(id);
        return ret;
    }

    @Override
    public Children getById(String id, String staffId) {
        Children ret = childrenRepository.getByIdAndStaffId(id, staffId);
        if (ret == null){
            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "宝宝不存在");
        }
        return ret;
    }

    @Override
    public Map<String, Object> getAllWithSourceByParent(Staff parent){

        String parentId = parent.getId();

        //获取关联家长的宝宝
        List<Children> refChildren = childrenRepository.findAllByParentPhoneAndDeletedIsFalse(parent.getMobile());

        //获取自有的宝宝
        List<Children> myChildren = childrenRepository.findByStaffIdAndDeletedIsFalseOrderByCreatedDesc(parentId);

        Children defaultChildren = defaultChildrenForParent(parent, false);

        if (defaultChildren != null){
            return ImmutableMap.of("ref", refChildren, "my", myChildren, "default", defaultChildren );
        }else {
            return ImmutableMap.of("ref", refChildren, "my", myChildren);
        }
    }

    @Override
    public List<Children> getAllByParent(Staff parent){
        String parentId = parent.getId();

        //获取关联家长的宝宝
        List<Children> refChildren = childrenRepository.findAllByParentPhoneAndDeletedIsFalse(parent.getMobile());

        //获取自有的宝宝
        List<Children> myChildren = childrenRepository.findByStaffIdAndDeletedIsFalseOrderByCreatedDesc(parentId);

        refChildren.addAll(myChildren);

        return refChildren;
    }

    public ChildrenExtendInfo getExtInfoByChildrenId(String childrenId){
        return childrenExtendInfoRepository.findByChildrenId(childrenId);
    }

    @Override
    public Children setDefaultChildren(Staff parent, String childrenId){
        //TODO ： 需要校验可见范围
        Children c = childrenRepository.getOne(childrenId);

        if (c == null){
            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "宝宝不存在");
        }

        RelStaffChildren rsc = rscRepository.findByStaffId(parent.getId());
        if (rsc == null){
            rsc = new RelStaffChildren();
            rsc.setStaffId(parent.getId());
        }
        rsc.setDefaultChildrenId(childrenId);
        rscRepository.save(rsc);

        return c;
    }

    //
    @Override
    public Children defaultChildrenForParent(Staff parent) {
        return defaultChildrenForParent(parent, true);
    }

    @Override
    public Children defaultChildrenForParent(Staff parent, boolean withException){
        RelStaffChildren rsc = rscRepository.findByStaffId(parent.getId());
        if (rsc == null){
            Children c = defaultChildrenForParent(parent, null);

            if (c == null){
                if (withException) {
                    throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "没有宝宝");
                }else{
                    return null;
                }
            }

            rsc = new RelStaffChildren();
            rsc.setStaffId(parent.getId());
            rsc.setDefaultChildrenId(c.getId());
            rscRepository.save(rsc);

            c.setMonth(DateUtil.betweenMonths(new Date(), c.getBirthday()));

            return c;
        }else{
            Children c = childrenRepository.getOne(rsc.getDefaultChildrenId());
            if (c == null && withException){
                throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "未知错误");
            }
            c.setMonth(DateUtil.betweenMonths(new Date(), c.getBirthday()));
            return c;
        }
    }

    private Children defaultChildrenForParent(Staff parent, String preferChildrenId) {
        Children c = null;
        if (StringUtils.isEmpty(preferChildrenId)) {
            List<Children> childrenList = getAllByParent(parent);

            if (childrenList != null && childrenList.size() > 0) {
                c = childrenList.get(0);
            }
        } else {
            c = getById(preferChildrenId);
        }

        return c;
    }


    @Override
    public boolean deleteChildrenForStaff(String childrenId, String staffId){

        Children children = childrenRepository.getByIdAndStaffId(childrenId, staffId);
        if(children == null){
            throw  new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "没有找到对应的宝宝");
        }

        RelStaffChildren rsc = rscRepository.findByStaffId(staffId);
        if (rsc != null && rsc.getDefaultChildrenId().equals(childrenId)){
            throw new BusinessException(ErrorCode.CHILDREN_DEFAULT, "默认宝宝无法删除");
        }

        children.setDeleted(true);
        childrenRepository.save(children);
        return true;
    }

    @Override
    public boolean transferChildren(Staff sourceStaff, Staff targetStaff){

        Organization org = staffService.staffOrgnization(targetStaff);

        childrenRepository.updateAllChildrenFromTo(sourceStaff.getId(), targetStaff.getId(), org.getId());

        return true;
    }

    @Override
    public Integer countChildrenByStaffIds(List<String> ids, Date date){
        if (date != null){
            return childrenRepository.countAllByStaffIdInAndCreatedGreaterThanAndDeletedIsFalse(ids, date);
        }else{
            return childrenRepository.countAllByStaffIdInAndDeletedIsFalse(ids);
        }
    }
}
